package com.example.webrtcdemo.utils

import com.google.gson.Gson
import com.zhangke.websocket.util.LogUtil
import java.net.URLEncoder
import java.security.MessageDigest
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

object SigUtil {

    fun sigV1(secretKey: String, urlStr: String, queryParam: Map<String, List<String>>, payload: ByteArray?): String {
        val queryString = getQueryStr(queryParam)
        val payloadHash = getPayloadHash(payload ?: ByteArray(0))
        val strToSign = "$urlStr\n$queryString\n$payloadHash"
        val signHex = hmacSha256Hex(strToSign, secretKey.toByteArray())
        return "SigV1 $signHex"
    }

    fun sigBearer(secretKey: String, urlStr: String, queryParam: Map<String, List<String>>, payload: ByteArray?): String {
        val queryString = getQueryStr(queryParam)
        val payloadHash = getPayloadHash(payload ?: ByteArray(0))
        val strToSign = "$urlStr\n$queryString\n$payloadHash"
        val signHex = hmacSha256Hex(strToSign, secretKey.toByteArray())
        return "Bearer $signHex"
    }

    private fun getPayloadHash(payload: ByteArray): String {
        val digest = MessageDigest.getInstance("SHA-256")
        digest.update(payload)
        return digest.digest().joinToString("") { "%02x".format(it) }
    }

    private fun getQueryStr(queryParam: Map<String, List<String>>): String {
        val keys = queryParam.keys.map { formatQueryKey(it) }.sorted()
        val newQueries = queryParam.mapKeys { formatQueryKey(it.key) }

        val sb = StringBuilder()
        for (key in keys) {
            val values = newQueries[key]?.sorted() ?: emptyList()
            for (v in values) {
                sb.append("$key=${URLEncoder.encode(v, "UTF-8")}&")
            }
        }
        return sb.removeSuffix("&").toString()
    }

    private fun formatQueryKey(key: String): String {
        val encoded = URLEncoder.encode(key, "UTF-8")
        return encoded.replace("+", "%20")
    }

    private fun hmacSha256(data: String, key: ByteArray): ByteArray {
        val mac = Mac.getInstance("HmacSHA256")
        mac.init(SecretKeySpec(key, "HmacSHA256"))
        return mac.doFinal(data.toByteArray())
    }

    private fun hmacSha256Hex(data: String, key: ByteArray): String {
        return hmacSha256(data, key).joinToString("") { "%02x".format(it) }
    }

    private fun StringBuilder.removeSuffix(suffix: String): StringBuilder {
        if (this.endsWith(suffix)) {
            this.delete(length - suffix.length, length)
        }
        return this
    }
}